﻿using System;
using System.Diagnostics;

using Exif.Interfaces;

namespace Exif.Various
{
	///<summary>
	///Знаковая дробь
	///</summary>
	[DebuggerDisplay("{Value} ({Numerator}/{Denominator})")]
	public struct SRational : IRational<Int32>,
		IConvertible
	{
		#region Конструктор

		///<summary>
		///Конструктор
		///</summary>
		///<param name="numerator">Числитель</param>
		///<param name="denominator">Знаменатель</param>
		public SRational(Int32 numerator, Int32 denominator)
			: this()
		{
			this.Numerator = numerator;
			this.Denominator = denominator;
		}

		#endregion

		#region Implementation of IRational

		///<summary>
		///Числитель
		///</summary>
		object IRational.Numerator
		{
			get { return this.Numerator; }
			set { this.Numerator = (int)value; }
		}

		///<summary>
		///Знаменатель
		///</summary>
		object IRational.Denominator
		{
			get { return this.Denominator; }
			set { this.Denominator = (int)value; }
		}

		///<summary>
		///Число
		///</summary>
		public Double Value
		{
			get { return this.Numerator/(double)this.Denominator; }
		}

		#endregion

		#region Implementation of IRational<T>

		///<summary>
		///Числитель
		///</summary>
		public int Numerator { get; set; }

		///<summary>
		///Знаменатель
		///</summary>
		public Int32 Denominator { get; set; }

		#endregion

		#region Implementation of IConvertible

		///<summary>Returns the <see cref="T:System.TypeCode"></see> for this instance.</summary>
		///<returns>The enumerated constant that is the <see cref="T:System.TypeCode"></see> of the class or value type that implements this interface.</returns>
		///<filterpriority>2</filterpriority>
		public TypeCode GetTypeCode()
		{
			throw new NotImplementedException();
		}

		///<summary>Converts the value of this instance to an equivalent Boolean value using the specified culture-specific formatting information.</summary>
		///<returns>A Boolean value equivalent to the value of this instance.</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public bool ToBoolean(IFormatProvider provider)
		{
			return this.Numerator != 0;
		}

		///<summary>Converts the value of this instance to an equivalent Unicode character using the specified culture-specific formatting information.</summary>
		///<returns>A Unicode character equivalent to the value of this instance.</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public char ToChar(IFormatProvider provider)
		{
			return (char)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent 8-bit signed integer using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///An 8-bit signed integer equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public sbyte ToSByte(IFormatProvider provider)
		{
			return (sbyte)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent 8-bit unsigned integer using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///An 8-bit unsigned integer equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public byte ToByte(IFormatProvider provider)
		{
			return (byte)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent 16-bit signed integer using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///An 16-bit signed integer equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public short ToInt16(IFormatProvider provider)
		{
			return (short)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent 16-bit unsigned integer using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///An 16-bit unsigned integer equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public ushort ToUInt16(IFormatProvider provider)
		{
			return (ushort)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent 32-bit signed integer using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///An 32-bit signed integer equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public int ToInt32(IFormatProvider provider)
		{
			return (int)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent 32-bit unsigned integer using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///An 32-bit unsigned integer equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public uint ToUInt32(IFormatProvider provider)
		{
			return (uint)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent 64-bit signed integer using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///An 64-bit signed integer equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public long ToInt64(IFormatProvider provider)
		{
			return (long)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent 64-bit unsigned integer using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///An 64-bit unsigned integer equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public ulong ToUInt64(IFormatProvider provider)
		{
			return (ulong)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent single-precision floating-point number using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///A single-precision floating-point number equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public float ToSingle(IFormatProvider provider)
		{
			return (float)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent double-precision floating-point number using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///A double-precision floating-point number equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public double ToDouble(IFormatProvider provider)
		{
			return this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent <see cref="T:System.Decimal"></see> number using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///A <see cref="T:System.Decimal"></see> number equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public decimal ToDecimal(IFormatProvider provider)
		{
			return (decimal)this.Value;
		}

		///<summary>
		///Converts the value of this instance to an equivalent <see cref="T:System.DateTime"></see> using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///A <see cref="T:System.DateTime"></see> instance equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public DateTime ToDateTime(IFormatProvider provider)
		{
			throw new InvalidCastException();
		}

		///<summary>
		///Converts the value of this instance to an equivalent <see cref="T:System.String"></see> using the specified culture-specific formatting information.
		///</summary>
		///<returns>
		///A <see cref="T:System.String"></see> instance equivalent to the value of this instance.
		///</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param><filterpriority>2</filterpriority>
		public string ToString(IFormatProvider provider)
		{
			if (provider is RationalFormatInfo)
			{
				return (provider as RationalFormatInfo).Format("{0}", this, provider);
			}
			return RationalFormatInfo.Instance.Format("{0}", this, provider);
		}

		///<summary>Converts the value of this instance to an <see cref="T:System.Object"></see> of the specified <see cref="T:System.Type"></see> that has an equivalent value, using the specified culture-specific formatting information.</summary>
		///<returns>An <see cref="T:System.Object"></see> instance of type <paramref name="conversionType"/> whose value is equivalent to the value of this instance.</returns>
		///<param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information. </param>
		///<param name="conversionType">The <see cref="T:System.Type"></see> to which the value of this instance is converted. </param><filterpriority>2</filterpriority>
		public object ToType(Type conversionType, IFormatProvider provider)
		{
			//фтопку
			throw new NotImplementedException();
		}

		#endregion

		#region Перегруженные методы

		public override string ToString()
		{
			return ToString(RationalFormatInfo.Instance);
		}

		#endregion
	}
}